package com.cobra.activiti.controller;

import com.alibaba.fastjson.JSON;
import com.cobra.activiti.pojo.dto.MetaInfoDTO;
import com.cobra.activiti.pojo.param.ModelCreateParam;
import com.cobra.activiti.pojo.param.ModelSelectListParam;
import com.cobra.activiti.pojo.param.SingleIdParam;
import com.cobra.activiti.pojo.vo.ModelVO;
import com.cobra.activiti.pojo.vo.PageVO;
import com.cobra.activiti.response.ResultVOUtil;
import com.cobra.activiti.response.ReturnValueLoader;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import lombok.extern.slf4j.Slf4j;
import org.activiti.bpmn.converter.BpmnXMLConverter;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.editor.constants.ModelDataJsonConstants;
import org.activiti.editor.language.json.converter.BpmnJsonConverter;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.Model;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Author: Baron
 * @Description: 流程模型controller类
 * @Date: Created in 2019/6/19 23:24
 */
@RestController
@Slf4j
@RequestMapping("/model")
public class ModelController {

    @Autowired
    private RepositoryService repositoryService;


    /**
     * <p>
     * 查询模型分页信息
     * </p>
     *
     * @param requestParam
     * @return
     */
    @PostMapping("/selectList")
    public ReturnValueLoader<PageVO<ModelVO>> getModelList(//@ApiParam(name = "receiveSwitchUpdateRequestVO", value = "json格式", required = true)
                                                           @Valid @RequestBody ModelSelectListParam requestParam) {

        PageVO<ModelVO> result = new PageVO<>();

        Integer current = requestParam.getCurrent();
        Integer queryPage = current - 1;
        Integer size = requestParam.getSize();

        Long count = repositoryService.createModelQuery().count();
        Integer intCount = count.intValue();

        List<Model> models = repositoryService.createModelQuery().orderByCreateTime().desc().listPage(queryPage, size);

        List<ModelVO> modelVOList = models.stream().map(model -> {
            ModelVO modelVO = new ModelVO();
            modelVO.setId(model.getId());
            modelVO.setName(model.getName());
            MetaInfoDTO metaInfo = JSON.parseObject(model.getMetaInfo(), MetaInfoDTO.class);
            modelVO.setDescription(metaInfo.getDescription());
            modelVO.setCreateTime(model.getCreateTime());
            modelVO.setUpdateTime(model.getLastUpdateTime());
            return modelVO;
        }).collect(Collectors.toList());

        result.setTotal(intCount);
        result.setCurrent(current);
        result.setSize(size);
        result.setRecords(modelVOList);

        return ResultVOUtil.success(result);
    }


    /**
     * 创建流程模型
     *
     * @param modelCreateParam
     */
    @PostMapping("/create")
    public ReturnValueLoader create(//@ApiParam(name = "receiveSwitchUpdateRequestVO", value = "json格式", required = true)
                                    @Valid @RequestBody ModelCreateParam modelCreateParam) {
        try {
            //设置默认值
            String name = modelCreateParam.getName();
            String description = modelCreateParam.getDescription();
            int version = 1;
            String key = "1";
            ObjectMapper objectMapper = new ObjectMapper();
            ObjectNode editorNode = objectMapper.createObjectNode();
            editorNode.put("id", "canvas");
            editorNode.put("resourceId", "canvas");
            ObjectNode stencilSetNode = objectMapper.createObjectNode();
            stencilSetNode.put("namespace", "http://b3mn.org/stencilset/bpmn2.0#");
            editorNode.put("stencilset", stencilSetNode);
            Model modelData = repositoryService.newModel();

            ObjectNode modelObjectNode = objectMapper.createObjectNode();
            modelObjectNode.put(ModelDataJsonConstants.MODEL_NAME, name);
            modelObjectNode.put(ModelDataJsonConstants.MODEL_REVISION, version);
            modelObjectNode.put(ModelDataJsonConstants.MODEL_DESCRIPTION, description);
            modelData.setMetaInfo(modelObjectNode.toString());
            modelData.setName(name);
            modelData.setKey(key);

            //保存模型
            repositoryService.saveModel(modelData);
            repositoryService.addModelEditorSource(modelData.getId(), editorNode.toString().getBytes("utf-8"));
            return ResultVOUtil.success("创建成功！");
        } catch (Exception e) {
            log.error("流程创建失败，e={}", e.getMessage());
            e.printStackTrace();
            return ResultVOUtil.error("创建失败！");
        }
    }

    /**
     * 流程设计
     *
     * @param singleIdParam
     * @param request
     * @param response
     */
    @PostMapping("/edit")
    public void edit(//@ApiParam(name = "receiveSwitchUpdateRequestVO", value = "json格式", required = true)
                     @Valid @RequestBody SingleIdParam singleIdParam,
                     HttpServletRequest request, HttpServletResponse response) {
        try {
            response.sendRedirect(request.getContextPath() + "/modeler.html?modelId=" + singleIdParam.getId());
        } catch (IOException e) {
            log.error("查询错误！");
            e.printStackTrace();
        }
    }

    /**
     * 流程模型部署
     *
     * @param singleIdParam
     * @return
     */
    @PostMapping("/deploy")
    public ReturnValueLoader deploy(//@ApiParam(name = "receiveSwitchUpdateRequestVO", value = "json格式", required = true)
                                    @Valid @RequestBody SingleIdParam singleIdParam) {

        String modelId = singleIdParam.getId().toString();

        Model model = repositoryService.getModel(modelId);
        if (model == null) {
            log.error("流程模型不存在，modelId={}", modelId);
            return ResultVOUtil.error("部署的流程模型不存在！");
        }
        try {
            byte[] modelByte = repositoryService.getModelEditorSource(model.getId());
            if (modelByte == null) {
                log.error("模型数据为空，未设计好，modelId={}", modelId);
                return ResultVOUtil.error("模型数据为空,请先设计好，再部署！");
            }
            JsonNode modelNode = new ObjectMapper().readTree(modelByte);
            BpmnModel bpmnModel = new BpmnJsonConverter().convertToBpmnModel(modelNode);
            if (bpmnModel.getProcesses().size() == 0) {
                log.error("数据模型不符要求，至少设计一条主线流程！");
                return ResultVOUtil.error("数据模型不符要求，请至少设计一条主线流程！");
            }
            byte[] bpmnBytes = new BpmnXMLConverter().convertToXML(bpmnModel);
            //发布流程
            String processName = model.getName() + ".bpmn20.xml";
            Deployment deployment = repositoryService.createDeployment()
                    .name(model.getName())
                    .addString(processName, new String(bpmnBytes, "UTF-8"))
                    .deploy();
            model.setDeploymentId(deployment.getId());
            repositoryService.saveModel(model);
            log.info("流程发布成功，modelId={}", modelId);
            return ResultVOUtil.success("【" + model.getName() + "】流程发布成功！");
        } catch (Exception e) {
            log.error("modelId ={}，流程发布失败，e ={}", modelId, e);
            e.printStackTrace();
            return ResultVOUtil.error("流程发布失败！");
        }
    }

    /**
     * 删除
     *
     * @param singleIdParam
     */
    @PostMapping("/delete")
    public ReturnValueLoader delete(//@ApiParam(name = "receiveSwitchUpdateRequestVO", value = "json格式", required = true)
                                    @Valid @RequestBody SingleIdParam singleIdParam) {

        try {
            repositoryService.deleteModel(singleIdParam.getId().toString());
            return ResultVOUtil.success("删除成功！");
        } catch (NullPointerException e) {
            return ResultVOUtil.error("删除的信息不存在！");
        }

    }

}